//
//  FZFZDBTools.m
//
//  Created by 李忠 on 7/2/16.
//  Copyright © 2016 FZLZ. All rights reserved.
//

#import "FZDBTools.h"


@interface FZDBTools ()

//保存和key排序方式，用于有排序方式的值,taxis 是否排序
@property (nonatomic, assign) FZQuerySortType querySortType;
@property (nonatomic, strong) NSString *key;
@property (nonatomic, assign, getter=isTaxis) BOOL taxis;

@end

@implementation FZDBTools

//单例创建一个数据库
+ (instancetype)shareManagerWithFilePath:(NSString *)filePath{
    static FZDBTools *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        instance = [FZDBTools databaseWithPath:filePath];
        
        
    });
    return instance;
}

/**
 *  
 *  根据传递进来的SQL创建一个表
 *  @param sql 创建表的SQL
 *
 *  @return 创建成功返回YES， 失败返回NO
 */
- (BOOL)createTableSQL:(NSString *)sql{
    
    BOOL result = NO;
    if ([self open]) {
        result = [self executeUpdate:sql];
    }
    
    return result;
}


//根据提供的字典向表中插入数据
- (BOOL)insertWithTableName:(NSString *)tableName withNewValues:(NSDictionary *)newValues{
    
    NSString *sql = [self appenInsertWithTableName:tableName withNewValues:newValues];
    
    return [self executeUpdate:sql];
}

/**
 *  删除指定key的行
 *
 *  @param tableName 表明
 *  @param key       key:字段 value:值
 *
 *  @return
 */
- (BOOL)delWithTableName:(NSString *)tableName withKey:(NSDictionary *)key{
    
    NSString *sql = [NSString stringWithFormat:@"delete from %@ where %@ = %@",tableName, [[key allKeys] lastObject], [[key allValues] lastObject]];
    
    return [self executeUpdate:sql];
}

/**
 *  更新指定中的行 指定行的内容
 *
 *  @param tableName 数据库表名
 *  @param newValue  更新的字典 key: 字段名， value:值
 *  @param require   根据是什么条件来更新数据 key:字段名, value:值
 *
 *  @return YES:成功, NO:失败
 */
- (BOOL)upadateWithTableName:(NSString *)tableName newValue:(NSDictionary *)newValue require:(NSDictionary *)require{
    
    NSString *sql = [self tableName:tableName withNewValues:newValue withRquire:require];
    return [self executeUpdate:sql];
}

/**
 *  根据传过来的排序方式和key 值对数组进行排序
 *
 *  @param tableName     表名
 *  @param sort          排序方式
 *  @param key           根据什么字段排序
 *  @param scuccessBlock 成功传递一个字典数组回去key:字段名 value:表名
 *  @param errorBlock    错误传回错误信息
 */
- (void)queryAllWithTableName:(NSString *)tableName withSort:(FZQuerySortType)sort forKey:(NSString *)key withSuccessBlock:(SuccessBlcok)scuccessBlock withErrorBlock:(ErrorBlcok)errorBlock{
    
    self.querySortType = sort;
    self.taxis = YES;
    self.key = key;
    [self queryAllWithTableName:tableName withSuccessBlock:scuccessBlock withErrorBlock:errorBlock];
    
}


//查询数据中所有的数据
/**
 *  查询表中所有数据
 *  查询是一个耗时动作，所以我开一个子线成操作，若果成功返回到主线程
 *
 *  @param tableName     表名
 *  @param scuccessBlock 成功传递一个字典数组回去key:字段名 value:表名
 *  @param errorBlock    错误传回错误信息
 */
- (void)queryAllWithTableName:(NSString *)tableName withSuccessBlock:(SuccessBlcok)scuccessBlock withErrorBlock:(ErrorBlcok)errorBlock{
    
    NSString *string = @"";
    if (self.isTaxis) {
        switch (self.querySortType) {
            case FZQuerySortAsc:
                
                string = [NSString stringWithFormat:@"order by %@ asc", self.key];
                break;
            case FZQuerySortDesc:
                string = [NSString stringWithFormat:@"order by %@ desc", self.key];
                
                break;
        }
    }
    
    //开启线程子线程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        if (![self isExistsTable:tableName]) {
            if (errorBlock) {
                //有错误，回到主线程
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    NSDictionary *dict = @{NSLocalizedDescriptionKey:@"表名错误"};
                    NSError *error =  [NSError errorWithDomain:@"fzlz.com" code:-1 userInfo:dict];
                    
                    errorBlock(error);
                });
            }
            return;
        }
        
        //得到表中的字段名
        NSArray *colNameArr = [self getColNameForTalbe:tableName];
        //声明一个可变数组用于存储表中数据，表的每一行都用字典存储
        NSMutableArray *tableArrM = [NSMutableArray array];

        NSString *sql = [NSString stringWithFormat:@"select * from %@ %@", tableName, string];
        
        FMResultSet *set = [self executeQuery:sql];
        
        while ([set next]) {
            @autoreleasepool {
                NSMutableDictionary *tempDict = [NSMutableDictionary dictionary];
                
                [colNameArr enumerateObjectsUsingBlock:^(NSString *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    @autoreleasepool {
                        
                        tempDict[obj] = [set stringForColumnIndex:(int)idx];
                        
                    }
                    
                }];
                [tableArrM addObject:tempDict];
            }
            
        }
        if (scuccessBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                scuccessBlock(tableArrM.copy);
            });
        }
    
    });
}

//模糊查询
- (NSArray<NSDictionary *> *)queryAllProductWithWorld:(NSString *)search{
    return nil;
}

//判断表是否存在
- (BOOL)isExistsTable:(NSString *)tableName{
    NSString *sql = [NSString stringWithFormat:@"select count(*) from %@", tableName];
    FMResultSet *set = [self executeQuery:sql];
    NSInteger count = 0;
    while ([set next]) {
        count = [set intForColumnIndex:0];
    }
    
    return count > 0 ? YES : NO;
}

//返回字段名列表
- (NSArray *)getColNameForTalbe:(NSString *)tableName{
    NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info(%@)", tableName];
    FMResultSet *set = [self executeQuery:sql];
    
    NSMutableArray *arrM = [NSMutableArray array];
    while ([set next]) {
        [arrM addObject:[set stringForColumnIndex:1]];
    }
    
    return arrM.copy;
}



//根据传入字典拼接插入命令
- (NSString *)appenInsertWithTableName:(NSString *)tableName withNewValues:(NSDictionary *)dict{
    
    NSString *types = [self appenArr:[dict allKeys]];
    NSString *values = [NSString stringWithFormat:@"values%@",[self appenValues:[dict allValues]]];
    NSString *sql = [NSString stringWithFormat:@"insert into %@ %@ %@",tableName, types, values];
    return sql;
}
- (NSString *)appenArr:(NSArray *)arr{
    NSMutableString *strM = [NSMutableString stringWithString:@"("];
    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [strM appendFormat:@"%@", obj];

        if (idx < arr.count-1) {
            [strM appendString:@","];
        }
    }];
    [strM appendString:@")"];
    return strM.copy;
}
- (NSString *)appenValues:(NSArray *)arr{
    NSMutableString *strM = [NSMutableString stringWithString:@"("];
    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSString class]]) {
                [strM appendFormat:@"'%@'", obj];
        }else{
            [strM appendFormat:@"%@", obj];
        }
        if (idx < arr.count-1) {
            [strM appendString:@","];
        }
    }];
    
    [strM appendString:@")"];
    return strM.copy;
}




//拼接更新数据的数组
- (NSString *)tableName:(NSString *)tableName withNewValues:(NSDictionary *)values  withRquire:(NSDictionary *)require{
    

    //更新的新值
    NSString *newValue = [self appenArr:[values allKeys] appenValues:[values allValues]];
    //更新的条件
    NSString *requerement = @"";
    if (require) {
        requerement = [NSString stringWithFormat:@"where %@", [self appenArr:[require allKeys] appenValues:[require allValues]]];
    }
   

    NSString *sql = [NSString stringWithFormat:@"update %@ set %@ %@", tableName, newValue,requerement];
    
    return sql;
}
- (NSString *)appenArr:(NSArray *)arr appenValues:(NSArray *)vaArr{
    
    NSMutableString *strM = [NSMutableString string];
    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([vaArr[idx] isKindOfClass:[NSString class]]) {
            [strM appendFormat:@"%@ = '%@'", obj, vaArr[idx]];
        }else{
            [strM appendFormat:@"%@ = %@", obj, vaArr[idx]];
        }
        if (idx < arr.count-1) {
            [strM appendString:@", "];
        }
    }];
    
    return strM.copy;
}
@end
